package cloud.dao;

import cloud.beans.Anime;
import cloud.beans.Person;
import cloud.config.CacheController;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;

/**
 * Classe implémentant l'interface UtilisateurDao @see {@link AnimeDao}
 * @author Alexis JULIEN & R&eacute;mi OGNARD pour TERCA
 * @version 1.0
 */
public class PersonDao {
	
	/**
	 * L'objet permettant de faire le lien avec la table.
	 */
	private DatastoreService datastore;
	
	/**
	 * Emsemble des erreurs produites.
	 */
	private ArrayList<String> erreursDAO;
	
	public PersonDao() {
		
		this.datastore = DatastoreServiceFactory.getDatastoreService();
		erreursDAO = new ArrayList<String>();
	}
		
	/** Implémentation de la méthode définie dans l'interface UtilisateurDao 
	 * @see {@link AnimeDao#creer(Utilisateur)}
	*/
	public boolean creer( Person person ) throws DAOException {
		
		//create Entity type "Anime"
		Entity personEntity = new Entity("Person");
		
		//set Entity properties to Anime
		personEntity.setProperty("first_name", person.getFirstName());
		personEntity.setProperty("last_name", person.getLastName());
		
		//save Entity to the datastore
		datastore.put(personEntity);
		//save Entity in MemCache
		CacheController.put("person", person);
		
		return true;
	}
	
	/* Implémentation de la méthode définie dans l'interface UtilisateurDao */
    public Person trouver( long id ) {

    	Person person = new Person();
    	
    	//gets the Object in MemCache if it exists
    	if(CacheController.containsKey(id)) {
    		System.out.println("recupere dans le cache");
    		person = (Person) CacheController.get(id);
    	}
		
    	//else gets the Object in Datastore 
    	else {
    		System.out.println("recupere dans le datastore");
	    	try {
	    		Key key = KeyFactory.createKey("Person", id);
	    		Entity result = datastore.get(key);
	    		person = map( result );
	    		
	    		//save Entity to the MemCache
    	    	CacheController.put(result.getKey().getId(), person);
	    	}
	    	 catch ( SQLException | EntityNotFoundException e ) {
				erreursDAO.add( e.getMessage() );
			}
    	}
    	return person;
    }

	/* Implémentation de la méthode définie dans l'interface UtilisateurDao */
    public List<Person> lister() {
    	
    	List<Person> personList = new ArrayList<Person>();
    	Person person;
    		
    	try {
    		Query query = new Query("Person");
	    	List<Entity> results = datastore.prepare(query).asList(FetchOptions.Builder.withDefaults());  	
	    	
	    	for(Entity result : results){   
	    		person = map(result);
	    		//save Entity to the MemCache
	    		CacheController.put(result.getKey().getId(), person);
	    		personList.add(person);
	    	}
    	}
    	 catch ( SQLException e ) {
 			erreursDAO.add( e.getMessage() );
 		}
	    	
	    return personList;
    } 
	
	/**
	* Simple méthode utilitaire permettant de faire la correspondance (le
	* mapping) entre une ligne issue de la table des utilisateurs (un
	* ResultSet) et un bean Utilisateur.
	*/
	private static Person map( Entity result ) throws SQLException {
		
		Person person = new Person();
		
		person.setId( result.getKey().getId() );
		person.setFirstName( (String) result.getProperty( "first_name" ) );
		person.setLastName( (String) result.getProperty( "last_name" ) );

		return person;
	}

}
